{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Net(nn.Module):\n",
    "    def __init__(self): #定义神经网络结构, 输入数据 1x32x32\n",
    "        super(Net, self).__init__()\n",
    "        # 第一层（卷积层）\n",
    "        self.conv1 = nn.Conv2d(1,6,3) #输入频道1， 输出频道6， 卷积3x3\n",
    "        # 第二层（卷积层）\n",
    "        self.conv2 = nn.Conv2d(6,16,3) #输入频道6， 输出频道16， 卷积3x3\n",
    "        # 第三层（全连接层）\n",
    "        self.fc1 = nn.Linear(16*28*28, 512) #输入维度16x28x28=12544，输出维度 512\n",
    "        # 第四层（全连接层）\n",
    "        self.fc2 = nn.Linear(512, 64) #输入维度512， 输出维度64\n",
    "        # 第五层（全连接层）\n",
    "        self.fc3 = nn.Linear(64, 2) #输入维度64， 输出维度2\n",
    "    \n",
    "    def forward(self, x): #定义数据流向\n",
    "        x = self.conv1(x)\n",
    "        x = F.relu(x)\n",
    "        \n",
    "        x = self.conv2(x)\n",
    "        x = F.relu(x)\n",
    "        \n",
    "        x = x.view(-1, 16*28*28)\n",
    "        x = self.fc1(x)\n",
    "        x = F.relu(x)\n",
    "        \n",
    "        x = self.fc2(x)\n",
    "        x = F.relu(x)\n",
    "        \n",
    "        x = self.fc3(x)\n",
    "        \n",
    "        return x\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Net(\n",
      "  (conv1): Conv2d(1, 6, kernel_size=(3, 3), stride=(1, 1))\n",
      "  (conv2): Conv2d(6, 16, kernel_size=(3, 3), stride=(1, 1))\n",
      "  (fc1): Linear(in_features=12544, out_features=512, bias=True)\n",
      "  (fc2): Linear(in_features=512, out_features=64, bias=True)\n",
      "  (fc3): Linear(in_features=64, out_features=2, bias=True)\n",
      ")\n"
     ]
    }
   ],
   "source": [
    "net = Net()\n",
    "print(net)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[[[-0.5518,  0.0649,  0.9500,  ...,  0.2207, -1.1846, -0.5081],\n",
      "          [-0.5137,  0.6061,  0.2845,  ..., -0.6264, -0.8313,  0.4624],\n",
      "          [ 0.3367, -1.1461,  0.8586,  ..., -1.4342,  0.3141,  1.2599],\n",
      "          ...,\n",
      "          [-0.4495,  1.7554, -1.1736,  ..., -1.5489,  1.8449,  1.5590],\n",
      "          [-0.8913,  0.5652,  1.0342,  ..., -0.4757,  1.1992,  0.8304],\n",
      "          [ 0.1675, -1.3038,  2.6100,  ..., -1.1493,  0.3754, -0.3571]]]])\n",
      "torch.Size([1, 1, 32, 32])\n"
     ]
    }
   ],
   "source": [
    "#生成随机输入\n",
    "input_data = torch.randn(1,1,32,32) \n",
    "print(input_data)\n",
    "print(input_data.size())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[-0.0965,  0.0616]], grad_fn=<ThAddmmBackward>)\n",
      "torch.Size([1, 2])\n"
     ]
    }
   ],
   "source": [
    "# 运行神经网络\n",
    "out = net(input_data)\n",
    "print(out)\n",
    "print(out.size())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[-1.1073,  0.6537]])\n"
     ]
    }
   ],
   "source": [
    "# 随机生成真实值\n",
    "target = torch.randn(2)\n",
    "target = target.view(1,-1)\n",
    "print(target)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor(0.8014, grad_fn=<L1LossBackward>)\n"
     ]
    }
   ],
   "source": [
    "criterion = nn.L1Loss() # 定义损失函数\n",
    "loss = criterion(out, target) # 计算损失\n",
    "print(loss)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 反向传递\n",
    "net.zero_grad() #清零梯度\n",
    "loss.backward() #自动计算梯度、反向传递\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch.optim as optim\n",
    "\n",
    "optimizer = optim.SGD(net.parameters(), lr=0.01)\n",
    "optimizer.step()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[-0.1450,  0.1121]], grad_fn=<ThAddmmBackward>)\n",
      "torch.Size([1, 2])\n"
     ]
    }
   ],
   "source": [
    "out = net(input_data)\n",
    "print(out)\n",
    "print(out.size())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "pytorch",
   "language": "python",
   "name": "pytorch"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
